using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using HWEngine;
using HWEngine.Configuration;
using HWEngine.Tools;
using HandWriter.Properties;
using System.IO;

namespace HandWriter
{
	public partial class LetterEditorDialog : Form
	{
		private Letter _letter;
		private bool _updatingPropertiesControls;
		private bool _updatingContentControls;
		private bool _trackPoint;
		private LinesPointsSelectController _selection;

		private Image _backGround;
		private Image _backGroundClip;
		private Graphics _backGroundClipGraphics;
		private Graphics _backGroundSmall;
		private Rectangle _backGroundWindow;
		private bool _needToRedrawSmallBackGround = true;
		private int _shiftBackX;
		private int _shiftBackY;
		private float _scaleBack = 1;
		private float _oldWidth;
		private float _oldHeight;

		private bool _isHandTool;
		private int _mX;
		private int _mY;
		private readonly DoubleBufferGraphics _gfx = new DoubleBufferGraphics();

		Cursor _panCursor = new Cursor(new MemoryStream(HandWriter.Properties.Resources.PanToolCursor));
		Cursor _panCursorMouseDown = new Cursor(new MemoryStream(HandWriter.Properties.Resources.PanToolCursorMouseDown));

		private ActionManager _actionMananer;

		public Letter Letter
		{
			get { return _letter; }
		}

		public void LoadData(Letter l)
		{
			_letter = l;
			_selection = new LinesPointsSelectController(_letter);
			UpdateLetterPropertiesControls();
			UpdateLetterContentControls(true, true);
			edLineWidth.Value = (decimal) Config.Configuration.LineWidthInLetterEditor;
		}

		public void UpdateLetterContentControls()
		{
			UpdateLetterContentControls(false, false);
		}

		public void UpdateLetterContentControls(bool updateLettesList, bool updatePointsList)
		{
			_updatingContentControls = true;
			int i = 0;
			if (updateLettesList)
			{
				cmbLines.Items.Clear();
			}
			if (updatePointsList)
			{
				cmbPoints.Items.Clear();
			}

			if (!_selection.IsPointSelected)
			{
				edPointX.Value = 0;
				edPointX.Enabled = false;
				edPointY.Value = 0;
				edPointY.Enabled = false;
			}
			if (updateLettesList)
			{
				i = 0;
				cmbLines.Items.AddRange((Letter.Lines.Select(line => String.Format("Line {0}", ++i)).ToArray()));
			}
			if (_selection.IsLineSelected)
			{
				cmbLines.SelectedIndex = _selection.LineIndex;
				if (updatePointsList)
				{
					i = 0;
					cmbPoints.Items.AddRange(_selection.SelectedLine.Points.Select(point => String.Format("Point {0}", ++i)).ToArray());
				}
				if (_selection.IsPointSelected)
				{
					cmbPoints.SelectedIndex = _selection.PointIndex;

					edPointX.Enabled = true;
					edPointX.Value = (decimal) _selection.SelectedPoint.X;
					edPointY.Enabled = true;
					edPointY.Value = (decimal) _selection.SelectedPoint.Y;
				}
				edLineTension.Enabled = true;
				edLineTension.Value = (decimal) _selection.SelectedLine.Tension;
			}
			else
			{
				edLineTension.Enabled = false;
			}
			btnAddPoint.Enabled = _selection.IsLineSelected;
			btnDeleteLine.Enabled = _selection.IsLineSelected;
			btnDelPoint.Enabled = _selection.IsPointSelected && _selection.IsLineSelected;
			if (_selection.IsLineSelected && _selection.SelectedLine.Points.Count <= 2)
			{
				btnDelPoint.Enabled = false;
			}

			DrawAll();
			_updatingContentControls = false;
		}

		public void UpdateLetterPropertiesControls()
		{
			_updatingPropertiesControls = true;
			edLetterWidth.Value = (int) (Letter.Width*100);
			edSymbol.Text = Letter.Key;
			Text = "Edit Letter: " + Letter.Caption;
			_updatingPropertiesControls = false;
		}

		public LetterEditorDialog()
		{
			InitializeComponent();
			_actionMananer = new ActionManager();
			_gfx.InitDoubleBufferedGraphics(pictureBox1);

			chDrawNumbers.Checked = Config.Configuration.DrawPointNumbers;

			chUseBackGround.Checked = Config.Configuration.ShowBackground;

			_scaleBack = Config.Configuration.BackgroundScale;
			_shiftBackX = Config.Configuration.BackgroundShiftX;
			_shiftBackY = Config.Configuration.BackgroundShiftY;

			_oldWidth = pictureBox1.Width;
			_oldHeight = pictureBox1.Height;
		}

		private void pictureBox1_Paint(object sender, PaintEventArgs e)
		{
			_gfx.Render(e.Graphics);
		}

		public void DrawAll()
		{
			DrawToBuffer(_gfx.Graphics);
			pictureBox1.Refresh();
		}

		public void DrawToBuffer(Graphics g)
		{
			g.SmoothingMode = SmoothingMode.HighQuality;

			//erase bkgrnd
			g.Clear(Color.White);

			if (_backGroundClip != null)
			{
				g.DrawImageUnscaled(_backGroundClip, 0, 0);

				//draw background rectangle
				if (_needToRedrawSmallBackGround && _backGroundSmall != null)
				{
					_backGroundSmall.DrawImage(_backGround, picBackground.ClientRectangle);

					RectangleF camera = new RectangleF();
					float coeffX = (_backGroundSmall.VisibleClipBounds.Width / _backGround.Width);
					float coeffY = (_backGroundSmall.VisibleClipBounds.Height / _backGround.Height);
					camera.X = _backGroundWindow.X * coeffX;
					camera.Y = _backGroundWindow.Y * coeffY;
					camera.Width = _backGroundWindow.Width * coeffX;
					camera.Height = _backGroundWindow.Height * coeffY;
					_backGroundSmall.DrawRectangle(Pens.Red, camera.X, camera.Y, camera.Width, camera.Height);
					picBackground.Refresh();
					_needToRedrawSmallBackGround = false;

					lbZoomBackground.Text = string.Format("Zoom: {0}%", (int) ((1/_scaleBack)*100));
				}
			}
			else
			{
				lbZoomBackground.Text = string.Empty;
			}

			if (Letter == null) return;

			//draw dividers
			float shift = pictureBox1.Height / 4f;
			float width = pictureBox1.Width;
			float height = pictureBox1.Height;
			float vertDividerPos = (float) (shift + Letter.RealWidth);
			using (Pen pen = new Pen(Color.Silver))
			{
				pen.DashStyle = DashStyle.Dash;

				g.DrawLine(pen, new PointF(0, shift), new PointF(width, shift));
				g.DrawLine(pen, new PointF(0, 3*shift), new PointF(width, 3*shift));
				g.DrawLine(pen, new PointF(shift, 0), new PointF(shift, height));
				g.DrawLine(pen,
				           new PointF(vertDividerPos, 0),
				           new PointF(vertDividerPos, height)
					);
			}

			//draw letter
			Letter.Draw(g);

			DrawControlPoints(_gfx.Graphics, false);
		}

		private void DrawControlPoints(Graphics g, bool drawWithoutNumbersAndSymbols)
		{
			//draw control squares
			for (int lineIndex = 0; lineIndex < Letter.Lines.Count; lineIndex++)
			{
				Line line = Letter.Lines[lineIndex];
				for (int pointIndex = 0; pointIndex < line.Points.Count; pointIndex++)
				{
					var t = 4;
					
					PointF p = line.Points[pointIndex];
					if (pointIndex == _selection.PointIndex && lineIndex == _selection.LineIndex)
					{
						var grayInColor = Color.FromArgb(0, 255, 0);
						var grayOutColor = Color.FromArgb(t * 40 + 30, t * 20 + 40, t * 20 + 40, 255);

						g.DrawRectangle(new Pen(grayOutColor), p.X - 3, p.Y - 3, 7, 7);
						g.DrawRectangle(new Pen(grayInColor), p.X - 2, p.Y - 2, 5, 5);
					}
					else
					{
						var grayInColor = Color.FromArgb(t * 30 + 80, Color.White);
						var grayOutColor = Color.FromArgb(t * 40 + 30, t * 20 + 40, t * 20 + 40, t * 20 + 40);

						g.DrawRectangle(new Pen(grayOutColor), p.X - 3, p.Y - 3, 7, 7);
						g.DrawRectangle(new Pen(grayInColor), p.X - 2, p.Y - 2, 5, 5);
					}

					if (Config.Configuration.DrawPointNumbers && !drawWithoutNumbersAndSymbols)
					{
						g.DrawString((pointIndex + 1).ToString(), SystemFonts.DialogFont, SystemBrushes.WindowText, p.X + 4, p.Y - 10);
					}
				}

				if (!drawWithoutNumbersAndSymbols)
				{
					if (line.StartIndex >= 0 && line.StartIndex < line.Points.Count)
					{
						PointF p = line.Points[line.StartIndex];
						if (line.StartConcatMode == ConcatMode.Abrupt)
						{
							g.DrawImage(Resources.AbruptConcat, p.X, p.Y);
						}
						if (line.StartConcatMode == ConcatMode.Smootly)
						{
							g.DrawImage(Resources.SoftConcat, p.X, p.Y);
						}
					}

					if (line.FinishIndex >= 0 && line.FinishIndex < line.Points.Count)
					{
						PointF p = line.Points[line.FinishIndex];
						if (line.FinishConcatMode == ConcatMode.Abrupt)
						{
							g.DrawImage(Resources.AbruptConcat, p.X, p.Y);
						}
						if (line.FinishConcatMode == ConcatMode.Smootly)
						{
							g.DrawImage(Resources.SoftConcat, p.X, p.Y);
						}
					}
				}
			}
		}

		private void UpdateLetterColor()
		{
			foreach (Line line in Letter.Lines)
			{
				line.Color = Color.Black;
			}
			if (_selection.IsLineSelected)
			{
				_selection.SelectedLine.Color = Color.Red;
			}
		}

		private bool FindPoint(Point coordinates, out int outlineIndex, out int outpointIndex)
		{
			outlineIndex = -1;
			outpointIndex = -1;

			//find a line and a point
			for (int lineIndex = 0; lineIndex < Letter.Lines.Count; lineIndex++)
			{
				Line line = Letter.Lines[lineIndex];
				for (int pointIndex = 0; pointIndex < line.Points.Count; pointIndex++)
				{
					if (CheckPoint(line.Points[pointIndex], coordinates))
					{
						outlineIndex = lineIndex;
						outpointIndex = pointIndex;
						return true;
					}
				}
			}

			return false;
		}

		private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
		{
			int pi, li;
			bool isPoint = FindPoint(e.Location, out li, out pi);
			
			if (!_isHandTool && isPoint)
			{
				//find a line and a point
				var oldLineIndex = _selection.LineIndex;
				var oldPointIndex = _selection.PointIndex;

				_selection.SetSelection(li, pi);
				UpdateLetterColor();

				UpdateLetterContentControls(
					_selection.LineIndex != oldLineIndex,
					_selection.LineIndex != oldLineIndex && _selection.PointIndex != oldPointIndex);

				if (e.Button == MouseButtons.Right)
				{
					menuPoint.Show(Cursor.Position.X, Cursor.Position.Y);
				}
				else
				{
					_trackPoint = true;
				}
			}
			else
			{
				if (e.Button == MouseButtons.Right)
				{
					TurnHandTool(!_isHandTool);
					return;
				}
			}
			
			if (_isHandTool)
			{
				//set cool cursor
				Cursor.Current = _panCursorMouseDown;
			}
			_mX = e.X;
			_mY = e.Y;
		}

		private static bool CheckPoint(PointF p1, Point p2)
		{
			return (Math.Abs(p1.X - p2.X) < 6 && Math.Abs(p1.Y - p2.Y) < 6);
		}

		private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
		{
			if (!_isHandTool)
			{
				_trackPoint = false;
				UpdateLetterContentControls();
			}
			else
			{
				Cursor.Current = _panCursor;
			}
			focusGrabberButton.Select();
		}

		private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
		{
			if (!_isHandTool)
			{
				if (_trackPoint)
				{
					_selection.UpdateSelectedPoint(new PointF(e.X, e.Y));
					
					DrawAll();
				}
			}
			else
			{
				if (e.Button == MouseButtons.Left)
				{
					int dx = e.X - _mX;
					int dy = e.Y - _mY;

					_shiftBackX -= Convert.ToInt32(Math.Round(dx*_scaleBack));
					_shiftBackY -= Convert.ToInt32(Math.Round(dy*_scaleBack));
					PrepareBackground();
					DrawAll();
				}
			}
			_mX = e.X;
			_mY = e.Y;
		}

		private void barWidth_ValueChanged(object sender, EventArgs e)
		{
			Letter.Width = (float) edLetterWidth.Value/100f;
			DrawAll();
		}

		public void SetLetterSize()
		{
			if (pictureBox1.Width > 0 && pictureBox1.Height > 0) //This zeros are when window goes to minimized stat
			{
				float scale = pictureBox1.Height/2f;
				Letter.SetScale(scale, scale);
				Letter.SetShift(scale/2, scale/2);
				PrepareBackground();
				DrawToBuffer(_gfx.Graphics);
			}
		}

		private void EditLetterForm_Shown(object sender, EventArgs e)
		{
			SetLetterSize();
		}

		private void EditLetterForm_Resize(object sender, EventArgs e)
		{
			_gfx.InitDoubleBufferedGraphics(pictureBox1);
			SetLetterSize();
		}

		private void edSymbol_TextChanged(object sender, EventArgs e)
		{
			try
			{
				if (!_updatingPropertiesControls)
				{
					if (edSymbol.Text.Length > 0)
					{
						Letter.Key = edSymbol.Text;
						UpdateLetterPropertiesControls();
					}
				}
			}
			catch
			{
			}
		}

		private void btnDeleteCurve_Click(object sender, EventArgs e)
		{
			_selection.DeleteLine();
			UpdateLetterColor();
			UpdateLetterContentControls(true, true);
		}

		private void btnDeletePoint_Click(object sender, EventArgs e)
		{
			DeleteSelectedPoint();
		}

		private PointF? GetAutoPoint()
		{
			if (_backGround == null)
			{
				return null;
			}

			return _selection.SelectedLine.GetNewPointCoordinates(
				(x, y) => ((Bitmap)_backGroundClip).GetPixel(x, y),
				_backGroundClip.Size);
		}

		private void btnAddPoint_Click(object sender, EventArgs e)
		{
			AddPoint();
		}

		private void AddPoint()
		{
			_selection.AddPoint(GetAutoPoint, -1);
			UpdateLetterContentControls(false, true);
		}

		private void btnAddCurve_Click(object sender, EventArgs e)
		{
			_selection.AddLine();
			Letter.SetLineWidth(Config.Configuration.LineWidthInLetterEditor);
			UpdateLetterColor();
			UpdateLetterContentControls(true, true);
		}

		private void cmbCurves_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (_updatingContentControls) return;
			focusGrabberButton.Select(); //grab focus
			if (Letter.Lines.Count > 0 && cmbLines.SelectedIndex < Letter.Lines.Count)
			{
				_selection.SetSelection(cmbLines.SelectedIndex, -1);

				UpdateLetterColor();
				UpdateLetterContentControls(false, true);
			}
		}

		private void cmbPoints_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (_updatingContentControls) return;
			focusGrabberButton.Select(); //grab focus

			_selection.SetSelection(_selection.LineIndex, cmbPoints.SelectedIndex);

			UpdateLetterContentControls();
		}

		private void EditLetterForm_FormClosed(object sender, FormClosedEventArgs e)
		{
			Config.Configuration.BackgroundScale = _scaleBack;
			Config.Configuration.BackgroundShiftX = _shiftBackX;
			Config.Configuration.BackgroundShiftY = _shiftBackY;
		}

		private void edLineWidth_ValueChanged(object sender, EventArgs e)
		{
			Config.Configuration.LineWidthInLetterEditor = (float) edLineWidth.Value;
			Letter.SetLineWidth(Config.Configuration.LineWidthInLetterEditor);
			DrawAll();
		}

		private void chDrawNumbers_CheckedChanged(object sender, EventArgs e)
		{
			Config.Configuration.DrawPointNumbers = chDrawNumbers.Checked;
			DrawAll();
		}

		private void PrepareBackground()
		{
			if (!Config.Configuration.ShowBackground) return;

			if (_backGround == null)
			{
				LoadBackGroundFile(Config.Configuration.BackgroundFileName);
			}

			if (_backGround != null)
			{
				if (_backGroundClipGraphics == null ||
				    pictureBox1.Width != _backGroundClip.Width ||
				    pictureBox1.Height != _backGroundClip.Height)
				{
					//relocate memory for drawing surface
					if (_backGroundClipGraphics != null) _backGroundClipGraphics.Dispose();
					if (_backGroundClip != null) _backGroundClip.Dispose();
					_backGroundClip = new Bitmap(pictureBox1.Width, pictureBox1.Height);
					_backGroundClipGraphics = Graphics.FromImage(_backGroundClip);
				}
				_scaleBack = (float) (_oldHeight/pictureBox1.Height)*_scaleBack;
				int w = Convert.ToInt32(pictureBox1.Width*_scaleBack);
				int h = Convert.ToInt32(pictureBox1.Height*_scaleBack);
				_backGroundWindow = new Rectangle(_shiftBackX, _shiftBackY, w, h);
				_backGroundClipGraphics.Clear(Color.White);
				_backGroundClipGraphics.DrawImage(_backGround, pictureBox1.ClientRectangle, _backGroundWindow, GraphicsUnit.Pixel);
				_needToRedrawSmallBackGround = true;
			}
			_oldWidth = pictureBox1.Width;
			_oldHeight = pictureBox1.Height;
		}


		private void btnLoadBackground_Click(object sender, EventArgs e)
		{
			if (openFileDialog1.ShowDialog() == DialogResult.OK)
			{
				LoadBackGroundFile(openFileDialog1.FileName);
			}
		}

		private void LoadBackGroundFile(string fileName)
		{
			if (String.IsNullOrEmpty(fileName)) return;
			try
			{
				picBackground.Image = new Bitmap(picBackground.ClientRectangle.Width, picBackground.ClientRectangle.Height);
				_backGroundSmall = Graphics.FromImage(picBackground.Image);
				_backGroundSmall.Clear(Color.White);

				_backGround = Image.FromFile(fileName);
				Config.Configuration.BackgroundFileName = fileName;
				PrepareBackground();
				DrawAll();
			}
			catch
			{
			}
		}

		private void btnZoomIn_Click(object sender, EventArgs e)
		{
			int oldW = Convert.ToInt32(pictureBox1.Width*_scaleBack);
			int oldH = Convert.ToInt32(pictureBox1.Height*_scaleBack);
			_scaleBack /= 1.1f;
			int w = Convert.ToInt32(pictureBox1.Width*_scaleBack);
			int h = Convert.ToInt32(pictureBox1.Height*_scaleBack);
			_shiftBackX += Convert.ToInt32((oldW - w)/2);
			_shiftBackY += Convert.ToInt32((oldH - h)/2);
			PrepareBackground();
			DrawAll();
		}

		private void btnZoomOut_Click(object sender, EventArgs e)
		{
			int oldW = Convert.ToInt32(pictureBox1.Width*_scaleBack);
			int oldH = Convert.ToInt32(pictureBox1.Height*_scaleBack);
			_scaleBack *= 1.1f;
			int w = Convert.ToInt32(pictureBox1.Width*_scaleBack);
			int h = Convert.ToInt32(pictureBox1.Height*_scaleBack);
			_shiftBackX += Convert.ToInt32((oldW - w)/2);
			_shiftBackY += Convert.ToInt32((oldH - h)/2);
			PrepareBackground();
			DrawAll();
		}

		private void btnHandTool_Click(object sender, EventArgs e)
		{
			TurnHandTool(btnHandTool.Checked);
		}

		private void TurnHandTool(bool isHand)
		{
			if (!Config.Configuration.ShowBackground)
			{
				return;
			}

			_isHandTool = isHand;
			btnHandTool.Checked = isHand;

			if (_isHandTool)
			{
				pictureBox1.Cursor = _panCursor;
			}
			else
			{
				pictureBox1.Cursor = Cursors.Default;
			}
		}

		private void chUseBackGround_CheckedChanged(object sender, EventArgs e)
		{
			Config.Configuration.ShowBackground = chUseBackGround.Checked;
			if (_updatingPropertiesControls) return;
			toolStripBackGround.Enabled = Config.Configuration.ShowBackground;
			if (!Config.Configuration.ShowBackground)
			{
				if (_backGroundClip != null)
				{
					_backGroundClip.Dispose();
					_backGroundClip = null;
				}
				if (_backGroundClipGraphics != null)
				{
					_backGroundClipGraphics.Dispose();
					_backGroundClipGraphics = null;
				}
			}
			else
			{
				PrepareBackground();
			}
			DrawAll();
		}

		private void edLineTension_ValueChanged(object sender, EventArgs e)
		{
			if (_selection.IsLineSelected)
			{
				_selection.SelectedLine.Tension = (float) edLineTension.Value;
			}
			DrawAll();
		}

		#region Moving And other Actions

		private void moveToolStripMenuItem1_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.MoveLeft));
		}

		private void moveRightToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.MoveRight));
		}

		private void moveUpToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.MoveUp));
		}

		private void moveDownToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.MoveDown));
		}

		private void increaseHorisontalToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.ScaleWidthIncrease));
		}

		private void increaseVerticalToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.ScaleHeightIncrease));
		}

		private void decreaseVerticalToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.ScaleHeightDecrease));
		}

		private void decseaseWidthToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.ScaleWidthDecrease));
		}

		#endregion

		private void copyToolStripMenuItem_Click(object sender, EventArgs e)
		{

		}

		private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
		{

		}

		private void undoToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (!_actionMananer.Empty)
			{
				_letter = _actionMananer.Pop();
				SetLetterSize();
				DrawAll();
			}
			if (_actionMananer.Empty)
			{
				undoToolStripMenuItem.Enabled = false;
			}
		}

		private void redoToolStripMenuItem_Click(object sender, EventArgs e)
		{

		}

		private void revertPointsInSelectedLineToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (_selection.IsLineSelected)
			{
				_selection.SelectedLine.Points.Reverse();
			}
			DrawAll();
		}

		private void ActionProcessor(Action a)
		{
			float scaleIncreaser = 1.1f;
			float scaleDecreaser = 1/scaleIncreaser;
			_actionMananer.Push(Letter);
			SetLetterSize();
			switch (a.ActionType)
			{
				case ActionType.MoveLeft:
					Letter.Shift(-1, 0);
					break;
				case ActionType.MoveRight:
					Letter.Shift(1, 0);
					break;
				case ActionType.MoveUp:
					Letter.Shift(0,-1);
					break;
				case ActionType.MoveDown:
					Letter.Shift(0, 1);
					break;
				case ActionType.ScaleWidthIncrease:
					Letter.Scale(scaleIncreaser, 1);
					break;
				case ActionType.ScaleHeightIncrease:
					Letter.Scale(1, scaleIncreaser);
					break;
				case ActionType.ScaleWidthDecrease:
					Letter.Scale(scaleDecreaser, 1);
					break;
				case ActionType.ScaleHeightDecrease:
					Letter.Scale(1, scaleDecreaser);
					break;
				case ActionType.ZoomIn:
					var p2 = Letter.GetCenterPoint();
					Letter.Scale(scaleIncreaser, scaleIncreaser);
					var p1 = Letter.GetCenterPoint();
					Letter.Shift(p2.X - p1.X, p2.Y - p1.Y);
					break;
				case ActionType.ZoomOut:
					Letter.Scale(scaleDecreaser, scaleDecreaser);
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}
			DrawAll();
			undoToolStripMenuItem.Enabled = true;
		}

		private void noCpncatenationToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_selection.SelectedLine.SetPointConcatMode(_selection.PointIndex, ConcatMode.None);
		}

		private void softConcatenationToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_selection.SelectedLine.SetPointConcatMode(_selection.PointIndex, ConcatMode.Smootly);
		}

		private void abruptConcatecationToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_selection.SelectedLine.SetPointConcatMode(_selection.PointIndex, ConcatMode.Abrupt);
		}

		private void linesPointsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			toolPanelLinesPoints.Visible = !toolPanelLinesPoints.Visible;
			UpdatePanelsCheckedState();
		}

		private void attributesToolStripMenuItem_Click(object sender, EventArgs e)
		{
			toolPanelAttributes.Visible = !toolPanelAttributes.Visible;
			UpdatePanelsCheckedState();
		}

		private void backgroundToolStripMenuItem_Click(object sender, EventArgs e)
		{
			toolPanelBackGround.Visible = !toolPanelBackGround.Visible;
			UpdatePanelsCheckedState();
		}

		private void toolPanelAttributes_OnCloseButtonClick(object sender, EventArgs e)
		{
			UpdatePanelsCheckedState();
		}

		private void UpdatePanelsCheckedState()
		{
			linesPointsToolStripMenuItem.Checked = toolPanelLinesPoints.Visible;
			attributesToolStripMenuItem.Checked = toolPanelAttributes.Visible;
			backgroundToolStripMenuItem.Checked = toolPanelBackGround.Visible;
		}

		private void edPointX_ValueChanged(object sender, EventArgs e)
		{
			if (!_updatingContentControls)
			{
				_selection.UpdateSelectedPoint(new PointF((float)edPointX.Value, (float)edPointY.Value));
				DrawAll();
			}
		}

		private void zoomInToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.ZoomIn));
		}

		private void zoomOutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActionProcessor(new Action(ActionType.ZoomOut));
		}

		private void deletePointToolStripMenuItem_Click(object sender, EventArgs e)
		{
			DeleteSelectedPoint();
		}

		private void DeleteSelectedPoint()
		{
			_selection.DeletePoint();
			UpdateLetterContentControls(false, true);
		}

		private void insertPointAfterToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_selection.AddPoint(GetAutoPoint, _selection.PointIndex);
			UpdateLetterContentControls(false, true);
		}

		private void insertPointBeforeToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_selection.AddPoint(GetAutoPoint, _selection.PointIndex - 1);
			UpdateLetterContentControls(false, true);
		}
	}
}